package com.yc.ATM;

import org.apache.log4j.Logger;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class BankServer {
    private static Logger log = Logger.getLogger(BankServer.class.getName());

    public static void main(String[] args) throws IOException {
//        CPU的核心数
        int processors=Runtime.getRuntime().availableProcessors();

//        核心线程池大小
        int corePoolSize = processors;

//        核心线程池的最大线程数
        int maxPoolSize = corePoolSize*2;

//        线程最大空闲时间
        long keepAliveTime = 10;
//        时间单位

        TimeUnit unit = TimeUnit.SECONDS;  //enum枚举  常量

//        阻塞队列  容量为2 最多允许放入两个空闲任务
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);  //同时最大任务量为 7  超过7个任务  则执行拒绝

//        线程创建工厂
        ThreadFactory threadFactory = new NameThreadFactory();

//        线程池拒绝策略
        RejectedExecutionHandler handler = new MyIgnorePolicy();

//        线程池执行器
        ThreadPoolExecutor executor = null;
//        推荐的创建线程池的方法  不推荐使用现成的API创建线程池
            executor = new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);

//            预启动所有核心线程  提升效率
            executor.prestartAllCoreThreads();


            Bank b = new Bank();
            ServerSocket ss = new ServerSocket(12000);
            log.info("银行服务器启动，监听" + ss.getLocalPort() + "端口");
            boolean flag = true;
            while (flag) {
                Socket s = ss.accept();
                System.out.println("ATM客户端:" + s.getRemoteSocketAddress() + "登录了服务器");
                //TODO: 商业项目必须用线程池
                //Thread t=new Thread(new BankTask(s,b));
                //t.start();

                BankTask task = new BankTask(s, b);
                //提交任务到线程池
                executor.submit(task);
            }

            executor.shutdown();
        }




    /***
     * 线程工厂
     */
    static class NameThreadFactory implements ThreadFactory{
        //线程id       AtomicInteger 原子类      原子整型类
        //原子性  可见性  有序性
        private final AtomicInteger threadId=new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable runnable) {           //getAndIncrement()生成数字 然后自增
            Thread t=new Thread(runnable,"线程-"+threadId.getAndIncrement());
            //System.out.println(t.getName()+"已经被创建");
            return t;
        }
    }


    //线程池拒绝策略
    public static class MyIgnorePolicy implements RejectedExecutionHandler{
        private Logger log=Logger.getLogger(MyIgnorePolicy.class.getName());
        @Override                      //被拒绝的任务                 线程池对象
        public void rejectedExecution(Runnable runnable, ThreadPoolExecutor e) {
            doLog(runnable,e);
        }
        private void doLog(Runnable runnable,ThreadPoolExecutor e){
            //可做日志记录等
            log.error("线程池："+e.toString()+runnable.toString()+" 被拒绝执行");
        }
    }

}

